//
//  Copyright 2021 Readium Foundation. All rights reserved.
//  Use of this source code is governed by the BSD-style license
//  available in the top-level LICENSE file of the project.
//

import Foundation

/// Problem Details for HTTP APIs.
///
/// https://tools.ietf.org/html/rfc7807
public struct HTTPProblemDetails: Decodable, Equatable {
    
    public enum Error: Swift.Error {
        case malformed(json: String?)
    }
    
    /// A short, human-readable summary of the problem type.
    public let title: String
    
    /// A URI reference [RFC3986] that identifies the problem type. This specification encourages
    /// that, when dereferenced, it provide human-readable documentation for the problem type.
    public let type: String?

    /// The HTTP status code ([RFC7231], Section 6) generated by the origin server for this
    /// occurrence of the problem.
    public let status: Int?
    
    /// A human-readable explanation specific to this occurrence of the problem.
    public let detail: String?
    
    /// A URI reference that identifies the specific occurrence of the problem.
    /// It may or may not yield further information if dereferenced.
    public let instance: String?

    public init(title: String, type: String? = nil, status: Int? = nil, detail: String? = nil, instance: String? = nil) {
        self.title = title
        self.type = type
        self.status = status
        self.detail = detail
        self.instance = instance
    }

    public init(data: Data) throws {
        guard
            let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
            let title = json["title"] as? String else
        {
            throw Error.malformed(json: String(data: data, encoding: .utf8))
        }
            
        self.init(
            title: title,
            type: json["type"] as? String,
            status: json["status"] as? Int,
            detail: json["detail"] as? String,
            instance: json["instance"] as? String
        )
    }
    
}

public extension MediaType {
    
    static let problemDetails = MediaType("application/problem+json")!
    
}
